/** @file    JSpaceCommImpl.cpp
 *  @author  Alessandro Polo
 *  @version $Id: JSpaceCommImpl.cpp 2891 2010-08-12 01:58:59Z alex $
 *  @brief
 * File containing methods for the JSpaceCommImpl class.
 * The header for this class can be found in JSpaceCommImpl.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include "JSpaceCommImpl.h"
 #include "JSpaceWrappers.h"

 #include <direct/conf.h>

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS

JSpaceCommImpl::JSpaceCommImpl( BundleGeneric& bundle )
	: BundleGenericWorker(bundle) {
	this->listener = NULL;

	this->dfb = NULL;
	this->events = NULL;

	this->display = false;
 }

JSpaceCommImpl::~JSpaceCommImpl() {
	Log(LOG_VERBOSE, ":~JSpaceCommImpl(): Destroying.." );
 }

//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////// THREAD RUN

bool JSpaceCommImpl::initializingThread() {
	Log(LOG_DEBUG, ":initializingThread(): STARTING" );

	return true;
 }

void JSpaceCommImpl::runThread() {
	Log(LOG_DEBUG, ":runThread(): Entering.." );

	while(this->running) {
		if ( !this->display ) {
			ThreadImpl::sleepForMSec(500);
			setThreadAlive();
			continue;
		 }

/*
		DFBCHECK( DiVineInit( NULL, NULL ) );
		DFBCHECK( DiVineCreate( &this->divine ) );

		sendKeyDown(HK_REMOTEAPP, 0, 0, ACT_Start);

		sendKeyDown(HK_HOMESCREEN, 0, 0, ACT_Start);
		sendKeyDown(DIKS_TUNER, 3, 0, ACT_Start);
		sendKeyDown(HK_MEDIA, MEDIA_USB,0,ACT_Start);
		sendKeyDown(HK_MEDIA, MEDIA_Network,0,ACT_Start);
		sendKeyDown(HK_HTML, 0, 0, ACT_Start);
		sendKeyDown(HK_DFU, 0, 0, ACT_Start);

		sendKeyDown(DIKS_CURSOR_UP, keySourceRc6, 0, rc6S0StepUp);
		sendKeyDown(DIKS_CURSOR_DOWN, keySourceRc6, 0, rc6S0StepDown);
		sendKeyDown(DIKS_CURSOR_RIGHT, keySourceRc6, 0, rc6S0StepRight);
		sendKeyDown(DIKS_CURSOR_LEFT, keySourceRc6, 0, rc6S0StepLeft);
		sendKeyDown(DIKS_OK, keySourceRc6, 0, rc6S0Acknowledge);

		DFBCHECK( (DFBResult)this->divine->Release(this->divine) );
		this->divine = NULL;
*/
		Log(LOG_INFO, ":runThread(): Pre-Initializing DirectFB.." );
		DFBCHECK( DirectFBInit( NULL, NULL ) );
		// now dfb_config is allocated
		setLogLevel(Log.getLevel());

		DFBResult res = DirectFBCreate( &this->dfb );
//		DFBResult ret = DirectFBSetOption( "quiet", "true" );

	//	DFBResult ret = dfb_config_init( NULL, NULL );


		Log(LOG_INFO, ":runThread(): Creating Displayer.." );
		jsDisplayer displayer;
		displayer.dfb = this->dfb;
		displayer.events = this->events;

	//	Log(LOG_INFO, ":runThread(): Waiting for player.." );
	//	displayer.waitForPlayer( 0, &this->running );


		Log(LOG_INFO, ":runThread(): Initializing Displayer.." );
		displayer.initialize();
		Log(LOG_INFO, ":runThread(): Entering Event loop of Displayer.." );
		displayer.enterLoop( &this->running );


		Log(LOG_INFO, ":runThread(): Deinitializing DirectFB.." );
		if ( this->events != NULL )
			DFBCHECK( (DFBResult)this->events->Release(this->events) );
		if ( this->dfb != NULL )
			DFBCHECK( (DFBResult)this->dfb->Release(this->dfb) );
	 }

	Log(LOG_DEBUG, ":runThread(): Exiting" );
 }

void JSpaceCommImpl::exitingThread() {
	Log(LOG_INFO, ":exitingThread() : .." );


 }

////////////////////////////////////////////////////////////////////////////////////////////////// THREAD RUN
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT JSpaceCommImpl::sendMessage( const std::string& message ) {
	this->display = !this->display;

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void JSpaceCommImpl::setLogLevel( wosh::LogLevel level ) {
	if ( direct_config == NULL ) return;
	switch( level ) {
		case LOG_NONE:
			direct_config->quiet = DMT_NONE;
			break;
		case LOG_CRITICAL:
			direct_config->quiet = DMT_ERROR;
			break;
		case LOG_WARNING:
			direct_config->quiet = DMT_WARNING;
			break;
		case LOG_INFO:
			direct_config->quiet = DMT_INFO;
			break;
		case LOG_ALL:
			direct_config->quiet = DMT_ALL;
			break;
		default:
			direct_config->quiet = DMT_ALL;
	 }
 // DMT_BANNER, DMT_UNIMPLEMENTED, DMT_ONCE
 }

std::string JSpaceCommImpl::getVersion() const {
	return Utilities::format("%d.%d.%d %d-%d", directfb_major_version, directfb_minor_version,directfb_micro_version, directfb_binary_age,directfb_interface_age);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

int JSpaceCommImpl::sendKeyDown( int keyname, int src, int sys, int cmd ) {
	if ( this->divine == NULL ) {
		return WRET_ERR_ILLEGAL_USE;
	 }
	DFBInputEvent event;
	unsigned long key_code;
		if ( divine ) {
		src |= NOTRCSOURCEMASK;
		key_code = (((unsigned int)src & 0xff) << 24) | (((unsigned int)sys & 0xff) << 16) | ((unsigned int)cmd & 0xffff);
		event.clazz = DFEC_INPUT;
		event.type = DIET_KEYPRESS;
		event.key_code = key_code;
		event.key_symbol = (DFBInputDeviceKeySymbol)keyname;
		event.flags = (DFBInputEventFlags)(DIEF_KEYCODE | DIEF_KEYSYMBOL);
		DFBResult err = this->divine->SendEvent (divine, &event);
		//DirectFBError (#x, err);
		return (WRESULT)err;
	 }
	return 1;
 }






























/*

     "  system=<system>                Specify the system (FBDev, SDL, etc.)\n"
     "  fbdev=<device>                 Open <device> instead of /dev/fb0\n"
     "  busid=<id>                     Specify the bus location of the graphics card (default 1:0:0)\n"
     "  mode=<width>x<height>          Set the default resolution\n"
     "  scaled=<width>x<height>        Scale the window to this size for 'force-windowed' apps\n"
     "  depth=<pixeldepth>             Set the default pixel depth\n"
     "  pixelformat=<pixelformat>      Set the default pixel format\n"
     "  surface-shmpool-size=<kb>      Set the size of the shared memory pool used\n"
     "                                 for shared system memory surfaces.\n"
     "  session=<num>                  Select multi app world (zero based, -1 = new)\n"
     "  remote=<host>[:<session>]      Select remote session to connect to\n"
     "  primary-layer=<id>             Select an alternative primary layer\n"
     "  primary-only                   Tell application only about the primary layer\n"
     "  [no-]banner                    Show DirectFB Banner on startup\n"
     "  [no-]surface-sentinel          Enable surface sentinels at the end of chunks in video memory\n"
     "  force-windowed                 Primary surface always is a window\n"
     "  force-desktop                  Primary surface is the desktop background\n"
     "  [no-]hardware                  Enable/disable hardware acceleration\n"
     "  [no-]software                  Enable/disable software fallbacks\n"
     "  [no-]software-warn             Show warnings when doing/dropping software operations\n"
     "  [no-]software-trace            Show every stage of the software rendering pipeline\n"
     "  [no-]dma                       Enable DMA acceleration\n"
     "  [no-]sync                      Do `sync()' (default=no)\n"
#ifdef USE_MMX
     "  [no-]mmx                       Enable mmx support\n"
#endif
     "  [no-]agp[=<mode>]              Enable AGP support\n"
     "  [no-]thrifty-surface-buffers   Free sysmem instance on xfer to video memory\n"
     "  font-format=<pixelformat>      Set the preferred font format\n"
     "  [no-]font-premult              Enable/disable premultiplied glyph images in ARGB format\n"
     "  [no-]deinit-check              Enable deinit check at exit\n"
     "  block-all-signals              Block all signals\n"
     "  [no-]vt-switch                 Allocate/switch to a new VT\n"
     "  vt-num=<num>                   Use given VT instead of current/new one\n"
     "  [no-]vt-switching              Allow Ctrl+Alt+<F?> (EXPERIMENTAL)\n"
     "  [no-]graphics-vt               Put terminal into graphics mode\n"
     "  [no-]vt                        Use VT handling code at all?\n"
     "  mouse-source=<device>          Mouse device for serial mouse\n"
     "  [no-]mouse-gpm-source          Enable mouse input repeated by GPM\n"
     "  [no-]motion-compression        Mouse motion event compression\n"
     "  mouse-protocol=<protocol>      Mouse protocol\n"
     "  [no-]lefty                     Swap left and right mouse buttons\n"
     "  [no-]capslock-meta             Map the CapsLock key to Meta\n"
     "  linux-input-ir-only            Ignore all non-IR Linux Input devices\n"
     "  [no-]linux-input-grab          Grab Linux Input devices?\n"
     "  [no-]cursor                    Never create a cursor or handle it\n"
     "  [no-]cursor-updates            Never show a cursor, but still handle it\n"
     "  wm=<wm>                        Window manager module ('default' or 'unique')\n"
     "  init-layer=<id>                Initialize layer with ID (following layer- options apply)\n"
     "  layer-size=<width>x<height>    Set the pixel resolution\n"
     "  layer-format=<pixelformat>     Set the pixel format\n"
     "  layer-depth=<pixeldepth>       Set the pixel depth\n"
     "  layer-buffer-mode=(auto|triple|backvideo|backsystem|frontonly|windows)\n"
     "  layer-bg-none                  Disable background clear\n"
     "  layer-bg-color=AARRGGBB        Use background color (hex)\n"
     "  layer-bg-color-index=<index>   Use background color index (decimal)\n"
     "  layer-bg-image=<filename>      Use background image\n"
     "  layer-bg-tile=<filename>       Use tiled background image\n"
     "  layer-src-key=AARRGGBB         Enable color keying (hex)\n"
     "  layer-palette-<index>=AARRGGBB Set palette entry at index (hex)\n"
     "  layer-rotate=<degree>          Set the layer rotation for double buffer mode (0,90,180,270)\n"
     "  [no-]smooth-upscale            Enable/disable smooth upscaling per default\n"
     "  [no-]smooth-downscale          Enable/disable smooth downscaling per default\n"
     "  [no-]translucent-windows       Allow translucent windows\n"
     "  [no-]decorations               Enable window decorations (if supported by wm)\n"
     "  [no-]startstop                 Issue StartDrawing/StopDrawing to driver\n"
     "  [no-]autoflip-window           Auto flip non-flipping windowed primary surfaces\n"
     "  videoram-limit=<amount>        Limit amount of Video RAM in kb\n"
     "  agpmem-limit=<amount>          Limit amount of AGP memory in kb\n"
     "  screenshot-dir=<directory>     Dump screen content on <Print> key presses\n"
     "  video-phys=<hexaddress>        Physical start of video memory (devmem system)\n"
     "  video-length=<bytes>           Length of video memory (devmem system)\n"
     "  mmio-phys=<hexaddress>         Physical start of MMIO area (devmem system)\n"
     "  mmio-length=<bytes>            Length of MMIO area (devmem system)\n"
     "  accelerator=<id>               Accelerator ID selecting graphics driver (devmem system)\n"
     "\n"
     "  [no-]matrox-sgram              Use Matrox SGRAM features\n"
     "  [no-]matrox-crtc2              Experimental Matrox CRTC2 support\n"
     "  matrox-tv-standard=(pal|ntsc|pal-60)\n"
     "                                 Matrox TV standard (default=pal)\n"
     "  matrox-cable-type=(composite|scart-rgb|scart-composite)\n"
     "                                 Matrox cable type (default=composite)\n"
     "  h3600-device=<device>          Use this device for the H3600 TS driver\n"
     "  mut-device=<device>            Use this device for the MuTouch driver\n"
     "  zytronic-device=<device>       Use this device for the Zytronic driver\n"
     "  elo-device=<device>            Use this device for the Elo driver\n"
     "  penmount-device=<device>       Use this device for the PenMount driver\n"
     "  linux-input-devices=<device>[[,<device>]...]\n"
     "                                 Use these devices for the Linux Input driver\n"
     "  tslib-devices=<device>[[,<device>]...]\n"
     "                                 Use these devices for the tslib driver\n"
     "  unichrome-revision=<rev>       Override unichrome hardware revision\n"
     "  i8xx_overlay_pipe_b            Redirect videolayer to pixelpipe B\n"
     "  include=<config file>          Include the specified file, relative to the current file\n"
     "\n"
     " Window surface swapping policy:\n"
     "  window-surface-policy=(auto|videohigh|videolow|systemonly|videoonly)\n"
     "     auto:       DirectFB decides depending on hardware.\n"
     "     videohigh:  Swapping system/video with high priority.\n"
     "     videolow:   Swapping system/video with low priority.\n"
     "     systemonly: Window surface is always stored in system memory.\n"
     "     videoonly:  Window surface is always stored in video memory.\n"
     "\n"
     " Desktop buffer mode:\n"
     "  desktop-buffer-mode=(auto|triple|backvideo|backsystem|frontonly|windows)\n"
     "     auto:       DirectFB decides depending on hardware.\n"
     "     triple:     Triple buffering (video only).\n"
     "     backvideo:  Front and back buffer are video only.\n"
     "     backsystem: Back buffer is system only.\n"
     "     frontonly:  There is no back buffer.\n"
     "     windows:    Special mode with window buffers directly displayed.\n"
     "\n"
     " Force synchronization of vertical retrace:\n"
     "  vsync-after:   Wait for the vertical retrace after flipping.\n"
     "  vsync-none:    disable polling for vertical retrace.\n"
*/